// pages/fivechess/fivechess.js
const {
 whiteIcon,
 blackIcon
} = require("../../utils/icon")
Page({
  data: {
    whiteIcon,
    blackIcon,
    title: '',
    CHESS_LATTICE: 15,
    NO_CHESS: 0,
    BLACK_CHESS: 2,
    WHITE_CHESS: 1,
    humanPlayer: 2,
    AIPlayer: 1,
    chessArr: [],
    recordChessArr: [],
    isPlayerTurn: true,
    isGameStart: false,
    ishand: 1,
    iscolor: 2,
    disksOpts: {
      disksNum: 0,
      disksTotal: 1
    }
  },
  onLoad(opts){
    // 初始化棋盘
    this.resetChessBoard();
    let disksOpts = wx.getStorageSync('disksOpts');
    if(disksOpts){
      this.setData({disksOpts})
    }
  },
  handBeforeAfter(e){
    let { hand:ishand } = e.currentTarget.dataset;
    this.setData({ishand, isPlayerTurn: ishand == 1 ? true : false})
  },
  commonClickMethod(e){
    let { name } = e.currentTarget.dataset;
    this[name](e)
  },
  getColor(e){
    let { color:iscolor } = e.currentTarget.dataset;
    this.setData({iscolor, humanPlayer: iscolor, AIPlayer: iscolor == 1 ? 2 : 1})
  },
  resetStart(){
    this.setData({isGameStart: false})
    this.resetChessBoard();
  },
  startGame(){
    this.setData({isGameStart: true, isPlayerTurn: this.data.ishand == 1 ? true : false});
    this.resetChessBoard();
    if(this.data.ishand == 2){
      this.AImoveChess();
    }
  },
  resetChessBoard(){
    let chessArr = [];
    let recordChessArr = [];
    let { CHESS_LATTICE, NO_CHESS} = this.data;
    for(let i = 0; i < CHESS_LATTICE; i++){
      chessArr[i] = [];
      for(let j = 0; j < CHESS_LATTICE; j++){
        let obj = {
          x: j,
          y: i,
          value: NO_CHESS
        };
        chessArr[i][j] = obj;
        recordChessArr.push(obj);
      }
    }
    this.setData({chessArr, recordChessArr})
  },
  _showToast(title, callback = () => {}){
    this.setData({title})
    setTimeout(() => {
      this.setData({title: ''})
    },1000);
  },
  getChessLatticeValue(e){
    if(!this.data.isGameStart){
      this._showToast('请【开始】游戏！');
      return;
    }
    if(!this.data.isPlayerTurn){
      this._showToast('AI正在思考，请耐心等待！');
      return;
    }
    let {index:i, idx:j} = e.currentTarget.dataset;
    this.PlayerMoveChess(i, j);
  },
  playChess(i, j, color){
    let chessArr = this.data.chessArr;
    if(chessArr[i][j].value){
      this._showToast('此处已落子，请另选他处！');
      return;
    }
    chessArr[i][j].value = color;
    this.setData({chessArr});
  },
  PlayerMoveChess(i, j){
    this.playChess(i, j, this.data.humanPlayer);
    this.data.isPlayerTurn = false;
    this.playerWinOrNot(i, j);
    if(this.data.isGameStart){
      this.AImoveChess();
    }
  },
  AImoveChess(){
    if(!this.data.isGameStart){
      this._showToast('请【开始】游戏！');
      return;
    }
    if(this.data.isPlayerTurn){
      this._showToast('玩家正在思考，请耐心等待！');
      return;
    }
    var maxX = 0,
        maxY = 0,
        maxWeight = 0,
        tem = 0;
    this.data.recordChessArr.filter(cur => cur.value === this.data.NO_CHESS).forEach(cur => {
      tem = this.computeWeight(cur.y, cur.x);
      if (tem > maxWeight) {
        maxWeight = tem;
        maxX = cur.x;
        maxY = cur.y;
      }
    })
    this.playChess(maxY, maxX, this.data.AIPlayer)
    this.data.isPlayerTurn = true;
    this.playerWinOrNot(maxY, maxX);
  },
  getWinsString(min, max, type, i){
    let { chessArr } = this.data;
    if(type === 'X'){
      return chessArr[i].filter((cur, index) => index >= min && index <= max);
    } else {
      let wins = [min++,min++,min++,min++,min++,min++,min++,min++,min++,min++,min].map(cur => chessArr[cur])
      switch (type) {
        case 'Y':
          return wins.map(cur => cur && cur[i]);
        case 'XY':
          return wins.map(cur => {
            if(cur){
              return cur[i++];
            } 
            i++
            return undefined;
          });
        case 'YX':
          return wins.map(cur => {
            if(cur){
              return cur[i--];
            } 
            i--
            return undefined;
          });
        default:
          break;
      }
    }
  },
  playerWinOrNot(i, j){
    let minX = i - 5;
    let maxX = i + 5;
    let minY = j - 5;
    let maxY = j + 5;
    let AIType = '11111';
    let PlayerType = '22222';
    let wins = [
      this.getWinsString(minY, maxY, 'X', i),
      this.getWinsString(minX, maxX, 'Y', j),
      this.getWinsString(minX, maxX, 'XY', minY),
      this.getWinsString(minX, maxX, 'YX', maxY)
    ].map(cur => cur.filter(cur => cur).map(cur => cur.value).join(''))
    let ais = wins.filter(cur => cur.indexOf(AIType) > -1);
    let players = wins.filter(cur => cur.indexOf(PlayerType) > -1);
    if(ais.length || players.length){
      this.setData({isGameStart: false})
      this._showToast('游戏结束！')
      let disksOpts = this.data.disksOpts;
      disksOpts.disksTotal += 1;
      let humanPlayer = this.data.humanPlayer;
      humanPlayer = `${humanPlayer}${humanPlayer}${humanPlayer}${humanPlayer}${humanPlayer}`;
      if(players.length && players[0].indexOf(humanPlayer) > -1){
        disksOpts.disksNum += 1;
      }
      if(ais.length && ais[0].indexOf(humanPlayer) > -1){
        disksOpts.disksNum += 1;
      }
      this.setData({disksOpts})
      wx.setStorageSync('disksOpts', disksOpts)
    }
  },
  //计算下子至i,j的权重
  computeWeight(i, j) { 
    /**
     * initWeightValue 权重初始值
     * weight 基于棋盘位置权重
     * chessColor 棋子颜色
     * */
    let {CHESS_LATTICE, AIPlayer, BLACK_CHESS, WHITE_CHESS} = this.data;
    let initWeightValue = CHESS_LATTICE - 1;
    let weight = initWeightValue - (Math.abs(i - initWeightValue / 2) + Math.abs(j - initWeightValue / 2));
    let chessColor = AIPlayer === BLACK_CHESS ? BLACK_CHESS : WHITE_CHESS;
    let chessColor0 = AIPlayer !== BLACK_CHESS ? BLACK_CHESS : WHITE_CHESS;
    let isAI = true;
    let isPlayer = false;
    // return 0;
    /**
     * AI下子权重、player下子权重、x方向、y方向、左斜方向、右斜方向
     */
    return [
      this.putDirectX(i, j, chessColor),
      this.putDirectX(i, j, chessColor0),
      this.putDirectY(i, j, chessColor),
      this.putDirectY(i, j, chessColor0),
      this.putDirectXY(i, j, chessColor),
      this.putDirectXY(i, j, chessColor0),
      this.putDirectYX(i, j, chessColor),
      this.putDirectYX(i, j, chessColor0)
    ].map((cur, index) => this.weightStatus(cur.nums, cur.side1, cur.side2, index % 2 == 0 ? isAI :
      isPlayer)).reduce((acc, cur) => acc + cur, weight);
  },
  //权重方案   独：两边为空可下子，单：一边为空
  weightStatus(nums, side1, side2, isAI) {
    var weight = 0;
    switch (nums) {
      case 1:
        if (side1 && side2) {
          weight = isAI ? 15 : 10; //独一
        }
        break;
      case 2:
        if (side1 && side2) {
          weight = isAI ? 100 : 50; //独二
        } else if (side1 || side2) {
          weight = isAI ? 10 : 5; //单二
        }
        break;
      case 3:
        if (side1 && side2) {
          weight = isAI ? 500 : 200; //独三
        } else if (side1 || side2) {
          weight = isAI ? 30 : 20; //单三
        }
        break;
      case 4:
        if (side1 && side2) {
          weight = isAI ? 5000 : 2000; //独四
        } else if (side1 || side2) {
          weight = isAI ? 400 : 100; //单四
        }
        break;
      case 5:
        weight = isAI ? 100000 : 10000; //五
        break;
      default:
        weight = isAI ? 500000 : 250000;
        break;
    }
    return weight;
  },
  //下子到i，j X方向 结果: 多少连子 两边是否截断
  putDirectX(i, j, chessColor) {
    var m, n,
      nums = 1,
      side1 = false,
      side2 = false;
    let {chessArr, NO_CHESS} = this.data;
    for (m = j - 1; m >= 0; m--) {
      if (chessArr[i][m].value === chessColor) {
        nums++;
      } else {
        if (chessArr[i][m].value === NO_CHESS) {
          side1 = true;
        }
        break;
      }
    }
    for (m = j + 1; m < 15; m++) {
      if (chessArr[i][m].value === chessColor) {
        nums++;
      } else {
        if (chessArr[i][m].value === NO_CHESS) {
          side2 = true;
        }
        break;
      }
    }
    return {
      "nums": nums,
      "side1": side1,
      "side2": side2
    };
  },
  //下子到i，j Y方向 结果
  putDirectY(i, j, chessColor) {
    var m, n,
      nums = 1,
      side1 = false,
      side2 = false;
    let {chessArr, NO_CHESS} = this.data;
    for (m = i - 1; m >= 0; m--) {
      if (chessArr[m][j].value === chessColor) {
        nums++;
      } else {
        if (chessArr[m][j].value === NO_CHESS) {
          side1 = true;
        }
        break;
      }
    }
    for (m = i + 1; m < 15; m++) {
      if (chessArr[m][j].value === chessColor) {
        nums++;
      } else {
        if (chessArr[m][j].value === NO_CHESS) {
          side2 = true;
        }
        break;
      }
    }
    return {
      "nums": nums,
      "side1": side1,
      "side2": side2
    };
  },
  //下子到i，j XY方向 结果
  putDirectXY(i, j, chessColor) {
    var m, n,
      nums = 1,
      side1 = false,
      side2 = false;
    let {chessArr, NO_CHESS} = this.data;
    for (m = i - 1, n = j - 1; m >= 0 && n >= 0; m--, n--) {
      if (chessArr[m][n].value === chessColor) {
        nums++;
      } else {
        if (chessArr[m][n].value === NO_CHESS) {
          side1 = true;
        }
        break;
      }
    }
    for (m = i + 1, n = j + 1; m < 15 && n < 15; m++, n++) {
      if (chessArr[m][n].value === chessColor) {
        nums++;
      } else {
        if (chessArr[m][n].value === NO_CHESS) {
          side2 = true;
        }
        break;
      }
    }
    return {
      "nums": nums,
      "side1": side1,
      "side2": side2
    };
  },
  putDirectYX(i, j, chessColor) {
    var m, n,
      nums = 1,
      side1 = false,
      side2 = false;
    let {chessArr, NO_CHESS} = this.data;
    for (m = i - 1, n = j + 1; m >= 0 && n < 15; m--, n++) {
      if (chessArr[m][n].value === chessColor) {
        nums++; 
      } else {
        if (chessArr[m][n].value === NO_CHESS) {
          side1 = true;
        }
        break;
      }
    }
    for (m = i + 1, n = j - 1; m < 15 && n >= 0; m++, n--) {
      if (chessArr[m][n].value === chessColor) {
        nums++;
      } else {
        if (chessArr[m][n].value === NO_CHESS) {
          side2 = true;
        }
        break;
      }
    }
    return {
      "nums": nums,
      "side1": side1,
      "side2": side2
    };
  }
})